/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package kolsim;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

/**
 *
 * @author asage12
 */
public class KoLSim {

    public static void main(String[] args) throws IOException {
        //Statistics theStats = run8Bit(100000, 2.0, false);
        //Statistics theStats = runFcle(1000000, 2.5, 80, false, false, false);
        //Statistics theStats = runBelowdecks(100000, 1.5, 0, false);
        //Statistics theStats = runDoD(1000000, 1.5, 70);
        //Statistics theStats = runDesertOasis(1000000, 2.5, 0, 34, 0, 99999);
        //Statistics theStats = runTopFloor(1000000, 95, true);
        //Statistics theStats = runBasement(1000000, 95, false, true);
        //Statistics theStats = runBeach(1000000, 10, 1);
        //Statistics theStats = runFriars(1000000, 2.5, 85);
        //Statistics theStats = runInsults(1000000, 90, "mox", 3);
        //Statistics theStats = runGreaterThan(1000000, 80);
        //Statistics theStats = runOrcs(1000000, 2.0, false, true, 2);
        //Statistics theStats = runPirates(1000000, 1.0, 70);
        //Statistics theStats = runUpperChamber(1000000, 3.0, 50, 5, 0, 9);
        //Statistics theStats = runCranny(1000000, 85, 49);
        //Statistics theStats = runPalindome(1000000, 2.5, 75);
        //Statistics theStats = runBilliards(1000000, 75);
        //Statistics theStats = runLibrary(1000000, 75);
        //Statistics theStats = runBedroom(1000000, 20);
        //Statistics theStats = runForest(1000000, 85);
        //Statistics theStats = runWarStart(1000000, 85);
        //Statistics theStats = runAlcove(1000000, 65, 50);
        //Statistics theStats = runNook(1000000, 1.5);
        //Statistics theStats = runCellar(1000000, 60, 80, 3);
        //Statistics theStats = runSetSong(1000000, 80);
        //Statistics theStats = runPantry(1000000);
        //Statistics theStats = runHiddenCity(1000000, 4.0, 60, true, false, true);
        //Statistics theStats = runOldKnoll(1000000, 90, true);
        //Statistics theStats = runNewKnoll(1000000, true);
        //Statistics theStats = runNiche(1000000, 50);
        //Statistics theStats = runCyrpt(1000000, 6);
        //Statistics theStats = runHitS(1000000, 2.5, false);
        Statistics theStats = runFearMan(1000000);
        
        System.out.println("Mean: " + theStats.getMean());
        System.out.println("Standard Deviation: " + theStats.getStdDev());
        //theStats.printCsv("oldDO.csv");
        
        /*Statistics theStats2 = runPalindome(1000000, 2.5, 80);
        System.out.println("Mean: " + theStats2.getMean());
        System.out.println("Standard Deviation: " + theStats2.getStdDev());        
        Statistics theStats3 = runPalindome(1000000, 2.5, 85);
        System.out.println("Mean: " + theStats3.getMean());
        System.out.println("Standard Deviation: " + theStats3.getStdDev());        
        Statistics theStats4 = runPalindome(1000000, 2.5, 90);
        System.out.println("Mean: " + theStats4.getMean());
        System.out.println("Standard Deviation: " + theStats4.getStdDev());           
        Statistics theStats5 = runPalindome(1000000, 2.5, 95);
        System.out.println("Mean: " + theStats5.getMean());
        System.out.println("Standard Deviation: " + theStats5.getStdDev());    
        Statistics theStats6 = runPalindome(1000000, 2.5, 100);
        System.out.println("Mean: " + theStats6.getMean());
        System.out.println("Standard Deviation: " + theStats6.getStdDev());
        /*Statistics theStats7 = runCellar(1000000, 60, 300, 3);
        System.out.println("Mean: " + theStats7.getMean());
        System.out.println("Standard Deviation: " + theStats7.getStdDev());  */     
    }

    public static double runMine(int numTimes, double itemDrop, int combatRate, boolean shouldBanish) {
        
        Random rng = new Random();
        
        int totalTurns = 0;
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;

            List combatArr = new ArrayList();
            combatArr.add(0, "helmet");
            combatArr.add(1, "pants");
            combatArr.add(2, "mattock");
            List NCArr = new ArrayList();
            NCArr.add(0, "helmpants");
            NCArr.add(1, "pantsmatt");
            NCArr.add(2, "helmmatt");
            NCArr.add(3, "jackpot");

            HashMap ts = new HashMap();
            ts.put("pants", 0);
            ts.put("helmet", 0);
            ts.put("mattock", 0);
            ts.put("combatAdvs", combatArr);
            ts.put("NCAdvs", NCArr);
            ts.put("combatQueue", new ArrayList());
            ts.put("NCQueue", new ArrayList());
            ts.put("done", 0);             
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }

                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: HELMET
                if (curEnc == "helmet") {      

                    if (shouldBanish) {
                        if (ts.get("helmet") == 1) {
                            ((List)ts.get(listVar)).remove(curEnc);
                            totalTurns++;
                            continue;
                        }
                    }

                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) ts.put("helm", 1);
                    totalTurns++;
                } 

                // COMBAT: MATTOCK
                if (curEnc == "mattock") {      

                    if (shouldBanish) {
                        if (ts.get("mattock") == 1) {
                            ((List)ts.get(listVar)).remove(curEnc);
                            totalTurns++;
                            continue;
                        }
                    }

                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) ts.put("mattock", 1);

                    totalTurns++;
                }       

                // COMBAT: PANTS
                if (curEnc == "pants") {      

                    if (shouldBanish) {
                        if (ts.get("pants") == 1) {
                            ((List)ts.get(listVar)).remove(curEnc);
                            totalTurns++;
                            continue;
                        }
                    }

                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) ts.put("pants", 1);

                    totalTurns++;
                }      

                // NONCOMBAT: HELMET/PANTS
                if (curEnc == "helmpants") {
                    // Do we have NEITHER? If so, pick whichever one is in the queue.
                    if (ts.get("helmet") == 0 && ts.get("pants") == 0) {
                        if (((List)ts.get("combatQueue")).contains("pants")) {
                            ts.put("pants", 1);
                        }
                        else {
                            ts.put("helmet", 1);
                        }
                    }
                    else if (ts.get("helmet") == 0) {
                        ts.put("helmet", 1);
                    }
                    else if (ts.get("pants") == 0) {
                        ts.put("pants", 1);
                    }
                    totalTurns++;
                }

                // NONCOMBAT: PANTS/MATTOCK
                if (curEnc == "pantsmatt") {
                    // Do we have NEITHER? If so, pick whichever one is in the queue.
                    if (ts.get("pants") == 0 && ts.get("mattock") == 0) {
                        if (((List)ts.get("combatQueue")).contains("pants")) {
                            ts.put("pants", 1);
                        }
                        else {
                            ts.put("mattock", 1);
                        }
                    }
                    else if (ts.get("mattock") == 0) {
                        ts.put("mattock", 1);
                    }
                    else if (ts.get("pants") == 0) {
                        ts.put("pants", 1);
                    }
                    totalTurns++;
                }     

                // NONCOMBAT: HELM/MATTOCK
                if (curEnc == "helmmatt") {
                    // Do we have NEITHER? If so, pick whichever one is in the queue.
                    if (ts.get("helmet") == 0 && ts.get("mattock") == 0) {
                        if (((List)ts.get("combatQueue")).contains("mattock")) {
                            ts.put("mattock", 1);
                        }
                        else {
                            ts.put("helmet", 1);
                        }
                    }
                    else if (ts.get("mattock") == 0) {
                        ts.put("mattock", 1);
                    }
                    else if (ts.get("helmet") == 0) {
                        ts.put("helmet", 1);
                    }
                    totalTurns++;
                }      

                // NONCOMBAT: LOCKER
                if (curEnc == "jackpot") {
                    if (ts.get("helmet") == 0) {
                        ts.put("helmet", 1);
                    }
                    else if (ts.get("mattock") == 0) {
                        ts.put("mattock", 1);
                    }
                    else if (ts.get("pants") == 0) {
                        ts.put("pants", 1);
                    }                      
                    totalTurns++;
                }

                // Are we done?
                if (ts.get("pants") == 1 && ts.get("helmet") == 1 && ts.get("mattock") == 1) {
                    isDone = true;
                    break;
                }
            }
        }
        
        double retVal = ((double)totalTurns / numTimes);
        
        return retVal;
    }        
    
    public static Statistics run8Bit(int numTimes, double itemDrop, boolean banishFirst) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            int numBanishes = 0;
            int whitePixels = 0;
            boolean blooperSniffed = false;
            String whichCreamed = "";
            double curTurns = 0;

            List combatArr = new ArrayList();
            combatArr.add("blooper");
            combatArr.add("bulletbill");
            combatArr.add("goomba");
            combatArr.add("keese");
            combatArr.add("koopatroopa");
            combatArr.add("octorok");
            combatArr.add("tektite");
            combatArr.add("zol");            
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curType = "combat";
                String curEnc = "none";                

                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichCreamed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: BLOOPER
                if ("blooper".equals(curEnc)) {      

                    if (banishFirst && numBanishes < 6) {
                        // just fight it
                    }
                    else {
                        if (!blooperSniffed) {
                            // sniff it
                            ((List)ts.get(listVar)).add(curEnc);
                            ((List)ts.get(listVar)).add(curEnc);
                            ((List)ts.get(listVar)).add(curEnc);
                            blooperSniffed = true;
                            whichCreamed = "blooper";
                        }
                    }
                    
                    int dropRoll1 = rng.nextInt(100) + 1;
                    if (dropRoll1 <= (80 * (1 + itemDrop))) whitePixels++;          
                    int dropRoll2 = rng.nextInt(100) + 1;
                    if (dropRoll2 <= (70 * (1 + itemDrop))) whitePixels++;  
                    int dropRoll3 = rng.nextInt(100) + 1;
                    if (dropRoll3 <= (60 * (1 + itemDrop))) whitePixels++;                      
                    curTurns++;
                } 

                // COMBAT: BULLET BILL
                if (curEnc == "bulletbill") {      
                    // banish this fucker no matter what
                    ((List)ts.get(listVar)).remove(curEnc);
                    numBanishes++;
                    curTurns++;
                }       

                // COMBAT: 1 WHITE PIXEL DROPPERS
                if (curEnc == "goomba" || curEnc == "koopatroopa" || curEnc == "tektite") {     
                    
                    if (banishFirst && numBanishes < 5) {
                        ((List)ts.get(listVar)).remove(curEnc);
                        numBanishes++;
                        curTurns++;      
                        continue;
                    }
                    
                    int dropRoll1 = rng.nextInt(100) + 1;
                    if (dropRoll1 <= (50 * (1 + itemDrop))) whitePixels++;      
                    int dropRoll2 = rng.nextInt(100) + 1;
                    if (dropRoll2 <= 34) whitePixels++;                        
                    curTurns++;
                }      

                // COMBAT: SOLID PIXEL DROPPERS
                if (curEnc == "keese" || curEnc == "octorok" || curEnc == "zol") {      

                    if ((banishFirst || blooperSniffed) && numBanishes < 6) {
                        ((List)ts.get(listVar)).remove(curEnc);
                        numBanishes++;
                        curTurns++;
                        continue;
                    }

                    whitePixels++;
                    curTurns++;
                } 

                // Are we done?
                if (whitePixels >= 30) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }
    
    public static Statistics runFcle(int numTimes, double itemDrop, int combatRate, boolean banishAll, boolean banishChatty, boolean banishCrusty) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;

            List combatArr = new ArrayList();
            combatArr.add("chatty");
            combatArr.add("cleanly");
            combatArr.add("clingy");
            combatArr.add("creamy");
            combatArr.add("crusty");
            combatArr.add("curmudgeonly");

            HashMap ts = new HashMap();
            ts.put("shampoo", 0);
            ts.put("polish", 0);
            ts.put("mop", 0);
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());
            ts.put("done", 0);             
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curTurns++;
                        continue;
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }

                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: CHATTY
                if (curEnc == "chatty") {      
                    if (banishAll || banishChatty) {
                        ((List)ts.get(listVar)).remove(curEnc);
                    }
                    curTurns++;
                    continue;
                } 

                // COMBAT: CLEANLY
                if (curEnc == "cleanly") {      

                    if (banishAll) {
                        if (ts.get("shampoo") == 1) {
                            ((List)ts.get(listVar)).remove(curEnc);
                            curTurns++;
                            continue;
                        }
                    }

                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (30 * (1 + itemDrop))) ts.put("shampoo", 1);

                    curTurns++;
                }       

                // COMBAT: CLINGY
                if (curEnc == "clingy") {     
                    // Banish for free
                    ((List)ts.get(listVar)).remove(curEnc);
                    continue;
                }      

                // COMBAT: CREAMY
                if (curEnc == "creamy") {      

                    if (banishAll) {
                        if (ts.get("polish") == 1) {
                            ((List)ts.get(listVar)).remove(curEnc);
                            curTurns++;
                            continue;
                        }
                    }

                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (30 * (1 + itemDrop))) ts.put("polish", 1);

                    curTurns++;
                } 
                
                // COMBAT: CRUSTY
                if (curEnc == "crusty") {      
                    if (banishAll || banishCrusty) {
                        ((List)ts.get(listVar)).remove(curEnc);
                    }
                    curTurns++;
                    continue;
                }      
                
                // COMBAT: CURMUDGEONLY
                if (curEnc == "curmudgeonly") {      

                    if (banishAll) {
                        if (ts.get("mop") == 1) {
                            ((List)ts.get(listVar)).remove(curEnc);
                            curTurns++;
                            continue;
                        }
                    }

                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (30 * (1 + itemDrop))) ts.put("mop", 1);

                    curTurns++;
                }                 

                // Are we done?
                if (ts.get("shampoo") == 1 && ts.get("mop") == 1 && ts.get("polish") == 1) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }  
    
    public static Statistics runBelowdecks(int numTimes, double itemDrop, int maxBanishes, boolean banishFirst) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            int numBanishes = 0;
            int gaudyKeys = 0;
            boolean hasGuitar = false;
            String whichSniffed = "";
            double curTurns = 0;

            List combatArr = new ArrayList();
            combatArr.add("gaudy");
            combatArr.add("grassy");
            combatArr.add("gritty");
            combatArr.add("groovy");
            combatArr.add("grungy");         
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curType = "combat";
                String curEnc = "none";                

                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: GAUDY
                if ("gaudy".equals(curEnc)) {      

                    if (banishFirst && maxBanishes > 0 && numBanishes < maxBanishes) {
                        // just fight it
                    }
                    else {
                        if (whichSniffed == "") {
                            // sniff it
                            ((List)ts.get(listVar)).add(curEnc);
                            ((List)ts.get(listVar)).add(curEnc);
                            ((List)ts.get(listVar)).add(curEnc);
                            whichSniffed = "gaudy";
                        }
                    }
                    
                    gaudyKeys++;                   
                    curTurns++;
                } 

                // COMBAT: USELESS PIRATES
                if (curEnc == "grassy" || curEnc == "gritty" || curEnc == "groovy") {      
                    if (banishFirst || (whichSniffed == "gaudy" && maxBanishes > 0 && numBanishes < maxBanishes)) {
                        ((List)ts.get(listVar)).remove(curEnc);
                        numBanishes++;
                    }
                    curTurns++;
                }                

                // COMBAT: GRUNGY
                if (curEnc == "grungy") {      

                    int dropRoll = rng.nextInt(100) + 1;
                    
                    if (numBanishes >= maxBanishes) {
                        if (dropRoll <= (20 * (4 + itemDrop))) hasGuitar = true;
                    }
                    else if (dropRoll <= (20 * (1 + itemDrop))) hasGuitar = true;
                    
                    curTurns++;
                } 

                // Are we done?
                if (gaudyKeys >= 2) {
                    allData.add(curTurns);
                    isDone = true;
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;         
    }
    
    public static Statistics runDoD(int numTimes, double itemDrop, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
            int smallBoxen = 0;
            int largeBoxen = 0;

            List combatArr = new ArrayList();
            combatArr.add("acidblob");
            combatArr.add("kobold");
            combatArr.add("mindflayer");
            combatArr.add("mechanic");
            combatArr.add("bees");       
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "muscle");
            NCAdvs.add(1, "myst");
            NCAdvs.add(2, "moxie");
            NCAdvs.add(3, "store");            
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: ACID BLOB OR BEES
                if ("bees".equals(curEnc) || "acidblob".equals(curEnc)) {                        
                    curTurns++;
                } 

                // COMBAT: LARGE KOBOLD
                if ("kobold".equals(curEnc)) {      
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (40 * (1 + itemDrop))) smallBoxen++;
                    
                    curTurns++;
                }                

                // COMBAT: MIND FLAYER
                if ("mindflayer".equals(curEnc)) {      
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (20 * (1 + itemDrop))) largeBoxen++;
                    
                    curTurns++;
                } 
                
                // COMBAT: QUANTUM MECHANIC
                if ("mechanic".equals(curEnc)) {      
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (40 * (1 + itemDrop))) largeBoxen++;
                    
                    curTurns++;
                }                 

                // NONCOMBAT: MUSCLE/MYST/MOXIE
                if ("muscle".equals(curEnc) || "myst".equals(curEnc) || "moxie".equals(curEnc)) {
                    curTurns++;
                }
                
                // NONCOMBAT: LIGHTING STORE
                if ("store".equals(curEnc)) {
                    curTurns++;
                    allData.add(curTurns);
                    isDone = true;
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }    
    
    public static Statistics runDesertOasis(int numTimes, double itemDrop, int numClovers, int initSuperRate, int superIncrease, int combatCap) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
            int hydratedTurns = 0;
            int numFound = 0;
            int curClovers = numClovers;
            boolean hasMachine = false;
            
            List combatArr = new ArrayList();
            combatArr.add("blur");
            combatArr.add("oasis");
            combatArr.add("stone");
            combatArr.add("beatles");    
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());   
            
            int nextSuper = combatCap;
            int superRate = initSuperRate;
            
            while (!isDone) {
                if (numFound == 0) {
                    int encRoll = rng.nextInt(100) + 1;
                    if (encRoll < superRate || nextSuper <= 0) {
                        numFound = 1;
                        nextSuper = combatCap;
                        superRate = initSuperRate;
                    }
                    else {
                        nextSuper--;
                        superRate = superRate + superIncrease;                        
                    }
                    curTurns++;
                }
                else if (numFound > 0) {
                    
                    int encRoll = rng.nextInt(100) + 1;
                    
                    if (numFound > 1 && !hasMachine) {
                        
                        String listVar = "combatAdvs";
                        String queueVar = "combatQueue";      
                        String curEnc = "none";         

                        if (numFound == 2 && (encRoll < superRate || nextSuper <= 0)) {
                            curEnc = "superlikely";
                        }
                        else if (hydratedTurns <= 0) {
                            curEnc = "ultrahydrated";
                        }

                        while ("none".equals(curEnc)) {
                            int listSize = ((List)ts.get(listVar)).size();
                            int whichNum = rng.nextInt(listSize);
                            String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                            // Queue rejection
                            if (((List)ts.get(queueVar)).contains(whichEnc)) {
                                int rngReject = rng.nextInt(100) + 1;
                                if (rngReject > 75) {
                                    curEnc = whichEnc;
                                }
                                else {
                                    continue;
                                }
                            }
                            else {
                                curEnc = whichEnc;
                            } 
                        }

                        // Add encounter to queue and chop off end of queue
                        ((List)ts.get(queueVar)).add(0, curEnc);
                        if (((List)ts.get(queueVar)).size() > 5) {
                            List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                            ((List)ts.get(queueVar)).retainAll(toKeep);
                        }                            

                        if ("superlikely".equals(curEnc)) {
                            numFound++;
                            nextSuper = combatCap;
                            superRate = initSuperRate;
                            curTurns++;
                            hydratedTurns--;
                        }
                        
                        if ("ultrahydrated".equals(curEnc)) {
                            if (curClovers > 0) {
                                hydratedTurns = 20;
                                curClovers--;
                            }
                            else {
                                hydratedTurns = 5;
                            }
                            //if (numFound < 2) { 
                            //    nextSuper--;
                            //    superRate = superRate + superIncrease;
                            //}
                            curTurns++;
                        }
                        
                        if ("oasis".equals(curEnc) || "beatles".equals(curEnc) || "stone".equals(curEnc)) {
                            curTurns++;
                            if (numFound < 2) {
                                nextSuper--;
                                superRate = superRate + superIncrease;
                            }
                            hydratedTurns--;                            
                        }
                        
                        if ("blur".equals(curEnc)) {
                            int dropRoll = rng.nextInt(100) + 1;
                            if (dropRoll <= (30 * (1 + itemDrop))) hasMachine = true;
                            curTurns++;
                            hydratedTurns--;
                            if (numFound < 2) {
                                nextSuper--;
                                superRate = superRate + superIncrease;
                            }
                        }
                            
                    }
                    // Theoretical turn cap
                    else if (nextSuper <= 0) {
                        numFound++;             
                        hydratedTurns--;
                        curTurns++;
                        nextSuper = combatCap; 
                        superRate = initSuperRate;
                    }
                    // Oasis supers can override ultrahydrated
                    else if (encRoll < superRate && (numFound == 2 || // Stone rose
                                              numFound == 6 || // Pages
                                              numFound == 7 ||
                                              numFound == 8)) { 
                        numFound++;             
                        hydratedTurns--;
                        curTurns++;
                        nextSuper = combatCap;
                        superRate = initSuperRate;
                    }
                    else if (hydratedTurns <= 0) { // Ultrahydrated
                        if (curClovers > 0) {
                            hydratedTurns = 20;
                            curClovers--;
                        }      
                        else {
                            hydratedTurns = 5;
                        }
                        curTurns++;
                        //nextSuper--;
                        //superRate = superRate + superIncrease;
                    }
                    else if (encRoll < superRate) {
                        numFound++;             
                        hydratedTurns--;
                        curTurns++;   
                        nextSuper = combatCap;
                        superRate = initSuperRate;
                    }
                    else { // Combat
                        hydratedTurns--;
                        curTurns++;
                        nextSuper--;
                        superRate = superRate + superIncrease;
                    }
                }
                
                if (numFound >= 9) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;              
    }
    
    public static Statistics runTopFloor(int numTimes, int combatRate, boolean hasMohawk) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean wheelDone = false;
            boolean hitsDone = false;
            double curTurns = 0;
            int turnsSinceNC = 0;
    
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "steampunk");
            NCAdvs.add(1, "goth");
            NCAdvs.add(2, "punk");
            NCAdvs.add(3, "raver");            
            
            HashMap ts = new HashMap();         
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!wheelDone || !hitsDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    if (turnsSinceNC < 9) {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            listVar = "NCAdvs";
                            queueVar = "NCQueue";
                        }
                        else {
                            curType = "combat";
                            curEnc = "combat";                 
                        }   
                    }
                    else {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";                        
                    }
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("noncombat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                    turnsSinceNC++;
                } 

                // NONCOMBAT: STEAMPUNK
                if ("steampunk".equals(curEnc)) {
                    if (!wheelDone) {
                        wheelDone = true;
                    }
                    else if (!hitsDone) {
                        hitsDone = true;
                    }
                    turnsSinceNC = 0;
                    curTurns++;
                }
                
                // NONCOMBAT: GOTH (GOES TO STEAMPUNK)
                if ("goth".equals(curEnc)) {
                    if (!wheelDone) {
                        wheelDone = true;
                    }
                    else if (!hitsDone) {
                        hitsDone = true;
                    }
                    turnsSinceNC = 0;
                    curTurns++;
                }       
                
                // NONCOMBAT: PUNK ROCK
                if ("punk".equals(curEnc)) {
                    if (!wheelDone && hasMohawk) {
                        wheelDone = true;
                    }
                    else if (wheelDone && !hitsDone) { // Go to steampunk
                        hitsDone = true;
                    }
                    turnsSinceNC = 0;
                    curTurns++;
                }       
                
                // NONCOMBAT: RAVER (GOES TO PUNK ROCK)
                if ("raver".equals(curEnc)) {
                    if (!wheelDone && hasMohawk) {
                        wheelDone = true;
                    }
                    else if (wheelDone && !hitsDone) { // Go to steampunk
                        hitsDone = true;
                    }
                    turnsSinceNC = 0;
                    curTurns++;
                }                     
                
                if (wheelDone && hitsDone) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }    
    
    public static Statistics runBasement(int numTimes, int combatRate, boolean hasUmbrella, boolean hasAmulet) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            boolean hasDumbbell = false;
            double curTurns = 0;
            int turnsSinceNC = 0;
    
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "fitness");
            NCAdvs.add(1, "neckbeard");
            NCAdvs.add(2, "furry");          
            
            HashMap ts = new HashMap();         
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                if (curTurns >= 35) { // auto-finish
                    curTurns++;
                    allData.add(curTurns);
                    break;                    
                }
                
                // Combat/NC
                while (curType == "none") {
                    if (turnsSinceNC < 9) {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            listVar = "NCAdvs";
                            queueVar = "NCQueue";
                        }
                        else {
                            curType = "combat";
                            curEnc = "combat";                 
                        }   
                    }
                    else {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";                        
                    }
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("noncombat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                    turnsSinceNC++;
                } 

                // NONCOMBAT: STEAMPUNK
                if ("fitness".equals(curEnc)) {
                    if (hasAmulet) {
                        isDone = true;
                        curTurns++;
                    }
                    else if (!hasDumbbell) {
                        hasDumbbell = true;
                        curTurns++;
                    }
                    turnsSinceNC = 0;
                }
                
                // NONCOMBAT: GOTH (GOES TO STEAMPUNK)
                if ("neckbeard".equals(curEnc)) {
                    if (hasAmulet || hasDumbbell) {
                        isDone = true;
                        curTurns++;
                    }
                    else if (!hasDumbbell) {
                        hasDumbbell = true;
                        curTurns++;
                    }
                    turnsSinceNC = 0;
                }       
                
                // NONCOMBAT: PUNK ROCK
                if ("furry".equals(curEnc)) {
                    if (hasUmbrella || hasDumbbell || hasAmulet) {
                        isDone = true;
                        curTurns++;
                    }
                    else if (!hasDumbbell) {
                        hasDumbbell = true;
                        curTurns++;                        
                    }
                    turnsSinceNC = 0;
                }                      
                
                if (isDone) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }      
    
    public static Statistics runBeach(int numTimes, int combatRate, int totalBarrels) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            int numBarrels = 0;
            double curTurns = 0;              
            
            while (!isDone) {

                String curType = "none";          
         
                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                    }
                    else {
                        curType = "combat";               
                    }   
                }

                if ("combat".equals(curType)) {                        
                    numBarrels++;
                    curTurns++;
                } 

                if ("noncombat".equals(curType)) {
                    curTurns++;
                }
                
                if (numBarrels >= totalBarrels) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }    
    
    public static Statistics runFriars(int numTimes, double itemDrop, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            
            double curTurns = 0;
            int numWings = 0;
            
            // Elbow
    
            int turnsInZone = 0;
            
            boolean firstNC = false,
                    secondNC = false,
                    thirdNC = false;            
            
            List combatArr = new ArrayList();
            combatArr.add("demoninja");
            combatArr.add("gimp");
            combatArr.add("limp");          
            
            HashMap ts = new HashMap();         
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    if (turnsInZone == 5 && !firstNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                    
                    }
                    else if (turnsInZone == 10 && !secondNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                      
                    }
                    else if (turnsInZone == 15 && !thirdNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                       
                    }         
                    else {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            curEnc = "noncombat";
                        }
                        else {
                            curType = "combat";
                            listVar = "combatAdvs";
                            queueVar = "combatQueue";         
                        }   
                    }
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("combat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {  
                    if (!firstNC) {
                        firstNC = true;
                    }
                    else if (!secondNC) {
                        secondNC = true;
                    }
                    else if (!thirdNC) {
                        thirdNC = true;
                    }
                    curTurns++;
                    turnsInZone++;
                } 

                // COMBAT: NON-WINGS
                if ("demoninja".equals(curEnc) || "limp".equals(curEnc)) {
                    curTurns++;
                    turnsInZone++;
                }
                
                // COMBAT: WINGS
                if ("gimp".equals(curEnc)) {
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (30 * (1 + itemDrop))) numWings++;
                    turnsInZone++;
                    curTurns++;
                }                    
                
                if (thirdNC) {
                    break;
                }
            }
            
            // Neck
    
            combatArr = new ArrayList();
            combatArr.add("hellion");
            combatArr.add("pimp");
            combatArr.add("wimp");          
            
            ts = new HashMap();         
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList()); 
            
            firstNC = false;
            secondNC = false;
            thirdNC = false;     
            turnsInZone = 0;
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    if (turnsInZone == 5 && !firstNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                    
                    }
                    else if (turnsInZone == 10 && !secondNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                         
                    }
                    else if (turnsInZone == 15 && !thirdNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                        
                    }
                    else {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            curEnc = "noncombat";
                        }
                        else {
                            curType = "combat";
                            listVar = "combatAdvs";
                            queueVar = "combatQueue";         
                        }   
                    }

                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("combat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {  
                    if (!firstNC) {
                        firstNC = true;
                    }
                    else if (!secondNC) {
                        secondNC = true;
                    }
                    else if (!thirdNC) {
                        thirdNC = true;
                    }
                    curTurns++;
                    turnsInZone++;
                } 

                // COMBAT: NON-WINGS
                if ("hellion".equals(curEnc) || "wimp".equals(curEnc)) {
                    curTurns++;
                    turnsInZone++;
                }
                
                // COMBAT: WINGS
                if ("pimp".equals(curEnc)) {
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (30 * (1 + itemDrop))) numWings++;
                    turnsInZone++;
                    curTurns++;
                }                    
                
                if (thirdNC) {
                    break;
                }
            }         
            
            // Heart
    
            combatArr = new ArrayList();
            combatArr.add("archfiend");
            combatArr.add("gimp");
            combatArr.add("pimp");          
            
            ts = new HashMap();         
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList()); 
            
            firstNC = false;
            secondNC = false;
            thirdNC = false;     
            turnsInZone = 0;
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    if (turnsInZone == 5 && !firstNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                           
                    }
                    else if (turnsInZone == 10 && !secondNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                          
                    }
                    else if (turnsInZone == 15 && !thirdNC) {
                        curType = "noncombat";
                        curEnc = "noncombat";                         
                    }
                    else if (thirdNC) {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                            
                    }
                    else {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            curEnc = "noncombat";
                        }
                        else {
                            curType = "combat";
                            listVar = "combatAdvs";
                            queueVar = "combatQueue";         
                        }   
                    }

                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("combat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {  
                    if (!firstNC) {
                        firstNC = true;
                    }
                    else if (!secondNC) {
                        secondNC = true;
                    }
                    else if (!thirdNC) {
                        thirdNC = true;
                    }
                    curTurns++;
                    turnsInZone++;
                } 

                // COMBAT: NON-WINGS
                if ("archfiend".equals(curEnc)) {
                    curTurns++;
                    turnsInZone++;
                }
                
                // COMBAT: WINGS
                if ("pimp".equals(curEnc) || "gimp".equals(curEnc)) {
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (30 * (1 + itemDrop))) numWings++;
                    turnsInZone++;
                    curTurns++;
                }                    
                
                if (thirdNC && numWings >= 3) {
                    allData.add(curTurns);
                    isDone = true;                    
                    break;
                }
            }                
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }     
    
    public static Statistics runInsults(int numTimes, int combatRate, String mainStat, int maxInsults) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
            int numInsults = 0;
    
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "drinks");
            NCAdvs.add(1, "darts");
            NCAdvs.add(2, "karaoke");           
            
            HashMap ts = new HashMap();         
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                  
                    }    
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if (!"combat".equals(curEnc)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBATS (OR KARAOKE)
                if ("combat".equals(curEnc) || ("karaoke").equals(curEnc)) {                        
                    int didInsultWorkRoll = rng.nextInt(100) + 1;
                    if (didInsultWorkRoll <= 75) {
                        // Success: insulted
                        boolean acceptInsult = false;
                        while (!acceptInsult) {
                            int whichInsult = rng.nextInt(8) + 1;
                            if (numInsults < whichInsult) {
                                // We got a new insult!
                                numInsults++;
                                acceptInsult = true;
                            }
                            else {
                                // We already have this insult
                                int rejectInsult = rng.nextInt(100) + 1;
                                if (rejectInsult <= 50) {
                                    // Reject it and try again
                                }
                                else {
                                    // Accept it anyway, which is LAME
                                    acceptInsult = true;
                                }
                            }
                        }
                    }
                    else {
                        // Failure: pirate was embarrassed
                    }
                    curTurns++;
                }          

                // NONCOMBAT: DRINKS
                if ("drinks".equals(curEnc)) {
                    curTurns++;
                }
                
                // NONCOMBAT: DARTS
                if ("darts".equals(curEnc)) {
                    if ("myst".equals(mainStat)) {
                        curTurns++;
                    }
                    else {
                        // Combat, pasted because I'm lazy
                        int didInsultWorkRoll = rng.nextInt(100) + 1;
                        if (didInsultWorkRoll <= 75) {
                            // Success: insulted
                            boolean acceptInsult = false;
                            while (!acceptInsult) {
                                int whichInsult = rng.nextInt(8) + 1;
                                if (numInsults < whichInsult) {
                                    // We got a new insult!
                                    numInsults++;
                                    acceptInsult = true;
                                }
                                else {
                                    // We already have this insult
                                    int rejectInsult = rng.nextInt(100) + 1;
                                    if (rejectInsult <= 50) {
                                        // Reject it and try again
                                    }
                                    else {
                                        // Accept it anyway, which is LAME
                                        acceptInsult = true;
                                    }
                                }
                            }
                        }
                        else {
                            // Failure: pirate was embarrassed
                        }
                        curTurns++;                        
                    }
                }
                
                if (numInsults >= maxInsults) {
                    break;
                }
            }
            
            // We have all of our insults, so...
            // Add 1 turn for the map
            curTurns++;
            // Add 1 turn for the booty crab
            curTurns++;
            // Add 1 turn for getting the blueprints
            curTurns++;
            // Add 1 turn for getting the dentures
            curTurns++;
            // Add 1 turn for returning the dentures
            curTurns++;
            
            // And now it's time for beer pong.
            
            while (!isDone) {
                int firstInsult = rng.nextInt(8) + 1;
                if (numInsults >= firstInsult) {
                    int secondInsult = rng.nextInt(8) + 1;
                    while (secondInsult == firstInsult) {
                        secondInsult = rng.nextInt(8) + 1;
                    }
                    if (numInsults >= secondInsult) {
                        int thirdInsult = rng.nextInt(8) + 1;
                        while (thirdInsult == secondInsult || thirdInsult == firstInsult) {
                            thirdInsult = rng.nextInt(8) + 1;
                        }
                        if (numInsults >= thirdInsult) {
                            // You win!
                            curTurns++;
                            isDone = true;
                            break;
                        }
                    }
                }
                curTurns++;
            }
            
            allData.add(curTurns);
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }    
    
    public static Statistics runGreaterThan(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;   
            boolean hasPlus = false;
            int telepTurns = 0;
            
            while (!isDone) {
              
                String curType = "none";
                String curEnc = "none";                

                if (telepTurns > 0 && hasPlus) {
                    int superRNG = rng.nextInt(100) + 1;
                    if (superRNG <= 25) {
                        curTurns++;
                        allData.add(curTurns);
                        isDone = true;
                        break;
                    }
                    else {
                        curTurns++;
                        telepTurns--;
                        continue;
                    }
                }
                
                // Combat/NC
                while ("none".equals(curType)) {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        curEnc = "noncombat";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";
                    }    
                }                
                


                // Now we have the encounter. Let's do this.

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                } 
                
                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {
                    if (!hasPlus) {
                        hasPlus = true;
                        curTurns++;
                    }
                    else if (telepTurns <= 0) {
                        telepTurns = 5;
                        curTurns++;
                    }
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }    
    
    public static Statistics runOrcs(int numTimes, double itemDrop, boolean hasAxe, boolean hasStone, int numMinis) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
            
            // Bridge
            int numWood = rng.nextInt(4) + 12;
            int numScrews = rng.nextInt(4) + 12;
            
            // Miniature suspension bridges
            for (int b = 0; b < numMinis; b++) {
                numWood = numWood + 10;
                numScrews = numScrews + 10;
            }

            List combatArr = new ArrayList();
            combatArr.add("jacker");
            combatArr.add("nailer");
            combatArr.add("pipelayer");
            combatArr.add("screwer");
            
            String whichSniffed = "";

            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curEnc = "none";                               

                // Pick encounter
                if (curTurns == 20) {
                    curEnc = "pervert";
                }
                else {
                    while (curEnc == "none") {
                        int listSize = ((List)ts.get(listVar)).size();
                        int whichNum = rng.nextInt(listSize);
                        String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                        // Queue rejection
                        if (((List)ts.get(queueVar)).contains(whichEnc) && whichSniffed != whichEnc) {
                            int rngReject = rng.nextInt(100) + 1;
                            if (rngReject > 75) {
                                curEnc = whichEnc;
                            }
                            else {
                                continue;
                            }
                        }
                        else {
                            curEnc = whichEnc;
                        } 
                    }
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: JACKER
                if (curEnc == "jacker") {   
                    if ((hasStone && !hasAxe && whichSniffed != "jacker" && whichSniffed != "pipelayer") ||
                        ((numScrews - numWood > 4) && whichSniffed == "" && numScrews >= 25)) {
                        whichSniffed = curEnc;
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                    }
                    numWood++;
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) numScrews++; 
                    curTurns++;
                }      
                
                // COMBAT: NAILER
                if (curEnc == "nailer") {   
                    if ((!hasStone && hasAxe && whichSniffed != "nailer" && whichSniffed != "screwer") ||
                        ((numWood - numScrews > 4) && whichSniffed == "" && numWood >= 25)) {
                        whichSniffed = curEnc;
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                    }
                    numScrews++;
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) numWood++;  
                    curTurns++;
                }          
                
                // COMBAT: PIPELAYER
                if (curEnc == "pipelayer") {   
                    if ((hasStone && !hasAxe && whichSniffed != "jacker" && whichSniffed != "pipelayer") ||
                        ((numScrews - numWood > 4) && whichSniffed == "" && numScrews >= 25)) {
                        whichSniffed = curEnc;
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                    }
                    numWood++;
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) numScrews++;  
                    curTurns++;
                }                     

                // COMBAT: SCREWER
                if (curEnc == "screwer") {   
                    if ((!hasStone && hasAxe && whichSniffed != "nailer" && whichSniffed != "screwer") ||
                        ((numWood - numScrews > 4) && whichSniffed == "" && numWood >= 25)) {
                        whichSniffed = curEnc;
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                    }
                    numScrews++;
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) numWood++;     
                    curTurns++;
                }    
                
                // COMBAT: PERVERT
                if (curEnc == "pervert") {
                    numScrews = numScrews + 5;
                    numWood = numWood + 5;
                    curTurns++;
                }
                
                // Post-combat droppers
                if (hasAxe) {
                    int bonusWoodChance = rng.nextInt(100) + 1;
                    if (bonusWoodChance > 50) {
                        numWood++;
                    }
                }
                if (hasStone) {
                    int bonusScrewChance = rng.nextInt(100) + 1;
                    if (bonusScrewChance > 50) {
                        numScrews++;
                    }
                }        
                
                if (numWood >= 30 && numScrews >= 30) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }   
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    } 
    
    public static Statistics runPirates(int numTimes, double itemDrop, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
            boolean hasEyepatch = false,
                    hasPants = false,
                    hasParrot = false;

            List combatArr = new ArrayList();
            combatArr.add("sassy");
            combatArr.add("shady");
            combatArr.add("shifty");
            combatArr.add("smarmy");
            combatArr.add("swarthy");       
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "muscle");
            NCAdvs.add(1, "myst");
            NCAdvs.add(2, "moxie");
            NCAdvs.add(3, "jokes");       
            NCAdvs.add(4, "vote");   
            NCAdvs.add(5, "peterpan");   
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: SHADY/SHIFTY
                if ("shady".equals(curEnc) || "shifty".equals(curEnc)) {                        
                    curTurns++;
                } 

                // COMBAT: SASSY
                if ("sassy".equals(curEnc)) {      
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) hasPants = true;
                    
                    curTurns++;
                }                

                // COMBAT: SMARMY
                if ("smarmy".equals(curEnc)) {      
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) hasEyepatch = true;
                    
                    curTurns++;
                }      
                
                // COMBAT: SWARTHY
                if ("swarthy".equals(curEnc)) {      
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (10 * (1 + itemDrop))) hasParrot = true;
                    
                    curTurns++;
                }                   

                // NONCOMBAT: MUSCLE/MYST/MOXIE
                if ("muscle".equals(curEnc) || "myst".equals(curEnc) || "moxie".equals(curEnc)) {
                    curTurns++;
                }
                
                // NONCOMBATS: CHOICES
                if ("jokes".equals(curEnc)) {
                    if (((List)ts.get("combatQueue")).contains("smarmy") && !hasEyepatch) {
                        hasEyepatch = true;
                    }
                    else if (((List)ts.get("combatQueue")).contains("swarthy") && !hasParrot) {
                        hasParrot = true;
                    }
                    else if (!hasEyepatch && hasParrot) {
                        hasEyepatch = true;
                    }
                    else if (!hasParrot && hasEyepatch) {
                        hasParrot = true;
                    }
                    else {
                        hasEyepatch = true;
                    }
                    curTurns++;
                }
                
                if ("vote".equals(curEnc)) {
                    if (((List)ts.get("combatQueue")).contains("smarmy") && !hasEyepatch) {
                        hasEyepatch = true;
                    }
                    else if (((List)ts.get("combatQueue")).contains("sassy") && !hasPants) {
                        hasPants = true;
                    }
                    else if (!hasEyepatch && hasPants) {
                        hasEyepatch = true;
                    }
                    else if (!hasPants && hasEyepatch) {
                        hasPants = true;
                    }
                    else {
                        hasPants = true;
                    }
                    curTurns++;
                }       
                
                if ("peterpan".equals(curEnc)) {
                    if (((List)ts.get("combatQueue")).contains("swarthy") && !hasParrot) {
                        hasParrot = true;
                    }
                    else if (((List)ts.get("combatQueue")).contains("sassy") && !hasPants) {
                        hasPants = true;
                    }
                    else if (!hasParrot && hasPants) {
                        hasParrot = true;
                    }
                    else if (!hasPants && hasParrot) {
                        hasPants = true;
                    }
                    else {
                        hasPants = true;
                    }
                    curTurns++;
                }                  
                
                if (hasEyepatch && hasPants && hasParrot) {
                    allData.add(curTurns);
                    isDone = true;
                    break;                    
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }    
    
    public static Statistics runUpperChamber(int numTimes, double itemDrop, int combatRate, int numTangles, int banishHowMany, int ratchetsNeeded) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;

            List combatArr = new ArrayList();
            combatArr.add("rat");
            combatArr.add("asp");
            combatArr.add("servant");
            
            String whichSniffed = "";
            int numBanished = 0,
                numRatchets = 0,
                curTangles = numTangles;

            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curEnc = "none";                               

                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichSniffed != whichEnc) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: ASP OR SERVANT
                if ("asp".equals(curEnc) || "servant".equals(curEnc)) {   
                    if (banishHowMany > 0 && numBanished < banishHowMany) {
                        ((List)ts.get(listVar)).remove(curEnc);
                        numBanished++;
                    }
                    curTurns++;
                }      
                
                // COMBAT: RAT
                if ("rat".equals(curEnc)) {   
                    if ("".equals(whichSniffed)) {
                        whichSniffed = curEnc;
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                        ((List)ts.get(listVar)).add(curEnc);
                    }
                    if (curTangles > 0) {
                        int dropRoll = rng.nextInt(100) + 1;
                        if (dropRoll <= (20 * (1 + itemDrop))) numRatchets++;  
                        dropRoll = rng.nextInt(100) + 1;
                        if (dropRoll <= (20 * (1 + itemDrop))) numRatchets++;  
                        dropRoll = rng.nextInt(100) + 1;
                        if (dropRoll <= (20 * (1 + itemDrop))) numRatchets++;  
                        curTangles--;
                    }
                    else {
                        int dropRoll = rng.nextInt(100) + 1;
                        if (dropRoll <= (20 * (1 + itemDrop))) numRatchets++;                       
                    }
                    curTurns++;
                }            
                
                if (numRatchets >= ratchetsNeeded && ratchetsNeeded == 9) {
                    // Get and place the wheel
                    curTurns++; // get wheel
                    while (!isDone) {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Wheel!
                        if (rngNC > combatRate) {
                            curTurns++;
                            isDone = true;
                            allData.add(curTurns);
                            break;
                        }
                        else {
                            curTurns++;                
                        }    
                    }
                }   
                else if (numRatchets >= ratchetsNeeded) {
                    curTurns++; // wheel
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }     
    
    public static Statistics runCranny(int numTimes, int combatRate, int plusML, int remainingEvil) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            double curTurns = 0;
            boolean isDone = false;            
            
            while (!isDone) {
               
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        curEnc = "noncombat";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                 
                    }   
                }                

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                    remainingEvil--;
                } 

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {
                    curTurns++;
                    double sqML = Math.sqrt(plusML);
                    remainingEvil = remainingEvil - (int)sqML;
                    /*int rngRound = rng.nextInt(100) + 1;
                    if (rngRound > 50) {
                        remainingEvil = remainingEvil - (int)Math.ceil(sqML);
                    }
                    else {
                        remainingEvil = remainingEvil - (int)Math.floor(sqML);
                    }*/
                }                   
                
                if (remainingEvil <= 25) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }       
    
    public static Statistics runPalindome(int numTimes, double itemDrop, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            
            double curTurns = 0;
            int numSuperItems = 0;
            boolean hasHound = false;

            List combatArr = new ArrayList();
            combatArr.add("bobracecar");
            combatArr.add("bard");
            combatArr.add("olive");
            combatArr.add("flock");    
            combatArr.add("racecarbob");    
            combatArr.add("cat");    
            combatArr.add("gnat");    
            
            HashMap ts = new HashMap();         
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    
                    // Do we meet superlikely conditions?
                    if (numSuperItems >= 3 && hasHound == true) {
                        // Drawn Onward
                        int superRNG = rng.nextInt(100) + 1;
                        if (superRNG <= 25) {
                            isDone = true;
                            allData.add(curTurns);
                            break;
                        }                   
                    }
                    if (numSuperItems < 1) {
                        int superRNG = rng.nextInt(100) + 1;
                        if (superRNG <= 25) {
                            curType = "superlikely";
                            curEnc = "superlikely";
                            break;
                        }                  
                    }
                    if (numSuperItems < 2) {
                        int superRNG = rng.nextInt(100) + 1;
                        if (superRNG <= 25) {
                            curType = "superlikely";
                            curEnc = "superlikely";
                            break;
                        }                  
                    }     
                    if (numSuperItems < 3) {
                        int superRNG = rng.nextInt(100) + 1;
                        if (superRNG <= 25) {
                            curType = "superlikely";
                            curEnc = "superlikely";
                            break;
                        }                  
                    }                    
                    
                    
                    if (curType == "none") {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            curEnc = "noncombat";
                        }
                        else {
                            curType = "combat";
                            listVar = "combatAdvs";
                            queueVar = "combatQueue";         
                        }   
                    }
                }       
                
                if (isDone == true) {
                    break;
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("combat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // SUPERLIKELY ITEMS
                if ("superlikely".equals(curEnc)) {
                    numSuperItems++;
                    curTurns++;
                }
                
                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {  
                    curTurns++;
                }
                
                // COMBAT: NON-NASCAR
                if ("bard".equals(curEnc) || "olive".equals(curEnc) || "flock".equals(curEnc) 
                    || "cat".equals(curEnc) || "gnat".equals(curEnc)) {
                    curTurns++;
                }
                
                // COMBAT: NASCAR
                if ("bobracecar".equals(curEnc) || "racecarbob".equals(curEnc)) {
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (35 * (1 + itemDrop))) hasHound = true;
                    curTurns++;
                }                    
            }
            
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }       
    
    public static Statistics runBilliards(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            
            double curTurns = 0;
            boolean hasCue = false;                
            
            while (!isDone) {
               
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                if (!hasCue) {
                    int superRNG = rng.nextInt(100) + 1;
                    if (superRNG <= 25) {
                        hasCue = true;
                        curTurns++;
                        continue;
                    }
                }
                
                if (curTurns >= 5 && hasCue) {
                    int rngNC = rng.nextInt(100) + 1;
                    if (rngNC > combatRate) {
                        curTurns++;
                        isDone = true;
                        allData.add(curTurns);
                        break;
                    }
                    else {
                        curTurns++;
                    }
                }
                else {
                    curTurns++;
                }
                
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }   
    
    public static Statistics runLibrary(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            
            double curTurns = 0;              
            
            while (!isDone) {             
                
                if (curTurns >= 5) {
                    int rngNC = rng.nextInt(100) + 1;
                    if (rngNC > combatRate) {
                        curTurns++;
                        isDone = true;
                        allData.add(curTurns);
                        break;
                    }
                    else {
                        curTurns++;
                    }
                }
                else {
                    curTurns++;
                }
                
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }   
    
    public static Statistics runBedroom(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            double curTurns = 0;
            int numWooden = 0;
            boolean isDone = false,
                    hasSpecs = false;
    
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "mahogany");
            NCAdvs.add(1, "ornate");
            NCAdvs.add(2, "white");
            NCAdvs.add(3, "wooden");            
            
            HashMap ts = new HashMap();         
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while ("none".equals(curType)) {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                 
                    }
                }                
                
                // Pick encounter
                while ("none".equals(curEnc)) {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    if ("wooden".equals(whichEnc) && curTurns < 5) {
                        continue;
                    }
                    
                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("noncombat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                } 

                // NONCOMBAT: USELESS ONES
                if ("mahogany".equals(curEnc) || "white".equals(curEnc)) {
                    curTurns++;
                }
                
                // NONCOMBAT: ORNATE
                if ("ornate".equals(curEnc)) {
                    if (!hasSpecs) {
                        hasSpecs = true;
                        curTurns++;
                        if (numWooden >= 2) {
                            allData.add(curTurns);
                            break;                              
                        }
                    }
                    else {
                        curTurns++;
                    }
                }       
                
                // NONCOMBAT: WOODEN
                if ("wooden".equals(curEnc)) {
                    if (numWooden == 0 || !hasSpecs) {
                        numWooden++;
                        curTurns++;
                    }
                    else if (numWooden >= 1 && hasSpecs) {
                        curTurns++;
                        allData.add(curTurns);
                        break;                        
                    }
                }       
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }   
    
    public static Statistics runForest(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            
            double curTurns = 0;
            int numNC = 0;
            int nextRespite = 6 + rng.nextInt(1);          
            
            while (!isDone) {
                
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    if (nextRespite == 0) {
                        curType = "noncombat";
                        curEnc = "noncombat";                    
                    }
                    else {
                        // Combat or noncombat?
                        int rngNC = rng.nextInt(100) + 1;

                        // Noncombats
                        if (rngNC > combatRate) {
                            curType = "noncombat";
                            curEnc = "noncombat";
                        }
                        else {
                            curType = "combat";
                            curEnc = "combat";        
                        }   
                    }
                }                

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {  
                    numNC++;
                    curTurns++;
                    nextRespite = 6 + rng.nextInt(1);
                } 

                // COMBAT
                if ("combat".equals(curEnc)) {
                    curTurns++;
                    nextRespite--;
                }                
                
                if (numNC >= 4) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }      
    
    public static Statistics runWarStart(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            double curTurns = 0;
            boolean isDone = false;
    
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "bait");
            NCAdvs.add(1, "sign");
            NCAdvs.add(2, "line");          
            
            HashMap ts = new HashMap();         
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                 
                    }   
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("noncombat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                } 

                // NONCOMBAT: USELESS ONES
                if ("bait".equals(curEnc) || "line".equals(curEnc)) {
                    curTurns++;
                }
                
                // NONCOMBAT: START THE WAR
                if ("sign".equals(curEnc)) {
                    curTurns++;
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }       
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }        
    
    public static Statistics runAlcove(int numTimes, int combatRate, int plusInit, int remainingEvil) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            double curTurns = 0;
            boolean isDone = false;            
            
            while (!isDone) {
               
                String curType = "none";
                String curEnc = "none";                

                // Superlikely
                int superRNG = rng.nextInt(100) + 1;
                if (superRNG <= (15 + (plusInit / 10))) {
                    curType = "superlikely";
                    curEnc = "modern";
                }
                
                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        curEnc = "noncombat";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                 
                    }   
                }                

                // MODERN
                if ("modern".equals(curEnc)) {                        
                    curTurns++;
                    remainingEvil = remainingEvil - 5;
                }                 
                
                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                    remainingEvil--;
                } 

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {
                    // reroll
                }                   
                
                if (remainingEvil <= 25) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }     
    
    public static Statistics runNook(int numTimes, double itemDrop, int remainingEvil) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            double curTurns = 0;
            boolean isDone = false;            
            
            while (!isDone) {            

                int dropRoll = rng.nextInt(100) + 1;
                if (dropRoll <= (20 * (1 + itemDrop))) remainingEvil = remainingEvil - 3;
                remainingEvil--;
                curTurns++;                
                
                if (remainingEvil <= 25) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }       

    public static Statistics runCellar(int numTimes, int combatRate, int plusML, int wantTangles) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            double curTurns = 0;
            int numTangles = 0,
                numSquares = 0;
            boolean isDone = false,
                    foundFaucet = false;          
            
            int faucetLocation = rng.nextInt(4) + 7;
            
            while (!isDone) {
               
                String curType = "none";
                String curEnc = "none";                

                if ((numSquares + 1) >= faucetLocation && !foundFaucet) {
                    curType = "special";
                    curEnc = "faucet";
                }
                
                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        curEnc = "noncombat";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                 
                    }   
                }      
                
                if ("combat".equals(curEnc)) {
                    int superRNG = rng.nextInt(100) + 1;
                    if (superRNG <= (plusML / 3)) {
                        curType = "combat";
                        curEnc = "king";
                    }                    
                }

                // RAT KING
                if ("king".equals(curEnc)) {
                    curTurns++;
                    numTangles++;
                    numSquares++;
                }                 
                
                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                    numSquares++;
                } 

                // NONCOMBAT
                if ("noncombat".equals(curEnc)) {
                    //curTurns++;
                    numSquares++;
                }        
                
                // FAUCET
                if ("faucet".equals(curEnc)) {
                    curTurns++;
                    foundFaucet = true;
                }
                
                if (foundFaucet && numTangles >= wantTangles) {
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }         
    
    public static Statistics runSetSong(int numTimes, int combatRate) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
    
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "curtains");
            NCAdvs.add(1, "quartet");       
            
            HashMap ts = new HashMap();         
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());               
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                
                
                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";
                    }
                    else {
                        curType = "combat";
                        curEnc = "combat";                 
                    }   
                }                
                
                // Pick encounter
                while (curEnc == "none") {
                    int listSize = ((List)ts.get(listVar)).size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = ((List)ts.get(listVar)).get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc)) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if ("noncombat".equals(curType)) {
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT
                if ("combat".equals(curEnc)) {                        
                    curTurns++;
                } 

                // NONCOMBAT: CURTAINS
                if ("curtains".equals(curEnc)) {
                    // Reroll
                }
                
                // NONCOMBAT: QUARTET
                if ("quartet".equals(curEnc)) {
                    curTurns++;
                    allData.add(curTurns);
                    break;
                }       
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }       
    
    public static Statistics runPantry(int numTimes) {
        
        Random rng = new Random();
        
        int i = 0;
        List<Double> allData = new ArrayList<Double>();
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;       
            
            while (!isDone) {
                if (curTurns < 8) {
                    curTurns++;
                }
                else if (curTurns == 8) {
                    int doneRNG = rng.nextInt(100) + 1;
                    if (doneRNG < 34) {
                        curTurns++;
                        allData.add(curTurns);
                        break;
                    }
                    curTurns++;
                }
                else if (curTurns == 9) {
                    int doneRNG = rng.nextInt(100) + 1;
                    if (doneRNG < 67) {
                        curTurns++;
                        allData.add(curTurns);
                        break;
                    }
                    curTurns++;
                }                
                else if (curTurns == 10) {
                    curTurns++;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;      
    }       
    
    public static Statistics runHiddenCity(int numTimes, double itemDrop, int combatRate, boolean migrateJanitors, boolean parkMatches, boolean banishOrderlies) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false,
                    hasMachete = false,
                    janitorsMigrated = false,
                    hasMatches = false,
                    orderliesBanished = false,
                    hasClip = false;
            int doctorPieces = 0,
                bowlingBalls = 0,
                reportPages = 0,
                numWrits = 0;
            String whichSniffed = "";
            double totalTurns = 0;
            double curTurns = 0;

            // The Hidden Park
            
            List combatArr = new ArrayList();
            combatArr.add("boaraffe");
            combatArr.add("assault");
            combatArr.add("blowgunner");

            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());         
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (curTurns >= 5 && rngNC > 50 && !hasMachete) {
                        curType = "superlikely";
                        curEnc = "superlikely";
                    }
                    else if (rngNC > combatRate) {
                        curType = "noncombat";
                        curEnc = "noncombat";
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                if (curType == "combat") {
                    // Add encounter to queue and chop off end of queue
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // SUPERLIKELY
                if (curEnc == "superlikely") {
                    hasMachete = true;
                    curTurns++;
                }
                
                // NONCOMBAT
                if (curEnc == "noncombat") {      
                    if (migrateJanitors && !janitorsMigrated) {
                        janitorsMigrated = true;
                        ((List)ts.get("combatAdvs")).add("janitor");
                        curTurns++;
                    }
                    else {
                        int dumpRNG = rng.nextInt(100) + 1;
                        if (dumpRNG > 50 && bowlingBalls < 3) {
                            bowlingBalls++;
                            curTurns++;
                        }
                        else {
                            if (doctorPieces < 5) {
                                doctorPieces++;
                            }
                            curTurns++;
                        }
                    }
                } 

                // COMBAT: USELESS
                if (curEnc == "boaraffe" || curEnc == "assault" || curEnc == "blowgunner") {      
                    curTurns++;
                }       

                // COMBAT: JANITOR
                if (curEnc == "janitor") {     
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (20 * (1 + itemDrop))) hasMatches = true;

                    curTurns++;
                }                

                // Are we done?
                if (hasMachete == true) {
                    if (parkMatches) {
                        if (hasMatches) {
                            totalTurns = totalTurns + curTurns;
                            break;
                        }
                    }
                    else {
                        totalTurns = totalTurns + curTurns;
                        break;
                    }
                }
            }
            
            // The Hidden Hospital
            
            curTurns = 0;
            
            combatArr.clear();
            combatArr.add("nurse");
            combatArr.add("surgeon");
            if (!orderliesBanished) {
                combatArr.add("orderlies");
            }
            if (!janitorsMigrated) {
                combatArr.add("janitor");
            }

            ts.clear();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());         
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC < (doctorPieces * 10)) {
                        curType = "noncombat";
                        curEnc = "noncombat";
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if (curType == "combat") {
                    // Add encounter to queue and chop off end of queue
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.
                
                // NONCOMBAT
                if (curEnc == "noncombat") {      
                    curTurns++;
                    totalTurns = totalTurns + curTurns;
                    break;                    
                } 

                // COMBAT: NURSE
                if (curEnc == "nurse") {      
                    curTurns++;
                }                      
                
                // COMBAT: ORDERLIES
                if (curEnc == "orderlies") {      
                    curTurns++;
                    if (banishOrderlies) {
                        ((List)ts.get(listVar)).remove(curEnc);
                    }
                }       

                // COMBAT: SURGEON
                if (curEnc == "surgeon") {   
                    if (whichSniffed != "surgeon") {
                        whichSniffed = "surgeon";
                    }
                    curTurns++;
                    if (doctorPieces < 5) {
                        doctorPieces++;
                    }
                }                     
                
                // COMBAT: JANITOR
                if (curEnc == "janitor") {     
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (20 * (1 + itemDrop))) hasMatches = true;

                    curTurns++;
                }                
            }        
            
            // The Hidden Bowling Alley
            
            curTurns = 0;
            
            combatArr.clear();
            combatArr.add("drunk");
            combatArr.add("bowler");
            if (!orderliesBanished) {
                combatArr.add("orderlies");
            }
            if (!janitorsMigrated) {
                combatArr.add("janitor");
            }

            ts.clear();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());         
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                curType = "combat";
                listVar = "combatAdvs";
                queueVar = "combatQueue";                    

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if (curType == "combat") {
                    // Add encounter to queue and chop off end of queue
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: DRUNK
                if (curEnc == "drunk") {      
                    if (hasMatches) {
                        ((List)ts.get(listVar)).remove(curEnc);
                    }
                    else {
                        curTurns++;
                    }
                }                      
                
                // COMBAT: ORDERLIES
                if (curEnc == "orderlies") {      
                    curTurns++;
                    if (banishOrderlies) {
                        ((List)ts.get(listVar)).remove(curEnc);
                    }
                }       

                // COMBAT: BOWLER
                if (curEnc == "bowler") { 
                    if (whichSniffed != "bowler") {
                        whichSniffed = "bowler";
                    }
                    curTurns++;
                    bowlingBalls++;
                }                     
                
                // COMBAT: JANITOR
                if (curEnc == "janitor") {     
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (20 * (1 + itemDrop))) hasMatches = true;

                    curTurns++;
                }          
                
                if (bowlingBalls >= 5) {
                    curTurns = curTurns + 5; // bowling NCs
                    totalTurns = totalTurns + curTurns;
                    break;                      
                }
            }     
            
            // The Hidden Apartment Building
            
            curTurns = 0;
            int turnsSinceNC = 0,
                curseLevel = 0;
            
            combatArr.clear();
            combatArr.add("shaman");
            combatArr.add("accountant");
            combatArr.add("lawyer");
            if (!janitorsMigrated) {
                combatArr.add("janitor");
            }

            ts.clear();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());         
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                if (turnsSinceNC >= 8) {
                    turnsSinceNC = 0;
                    curType = "noncombat";
                    curEnc = "noncombat";
                }
                else {
                    curType = "combat";
                    listVar = "combatAdvs";
                    queueVar = "combatQueue";          
                }

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if (curType == "combat") {
                    // Add encounter to queue and chop off end of queue
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: SHAMAN
                if (curEnc == "shaman") {      
                    if (!hasMatches && whichSniffed != "shaman") {
                        whichSniffed = "shaman";
                    }
                    curseLevel++;
                    curTurns++;      
                    turnsSinceNC++;
                }                      
                
                // COMBAT: ACCOUNTANT
                if (curEnc == "accountant") {  
                    if (hasMatches && reportPages < 5 && whichSniffed != "accountant") {
                        whichSniffed = "accountant";                        
                    }
                    reportPages++;
                    curTurns++;
                    turnsSinceNC++;
                }       

                // COMBAT: LAWYER
                if (curEnc == "lawyer") {    
                    if (hasMatches && reportPages >= 5 && whichSniffed != "lawyer") {
                        whichSniffed = "lawyer";                          
                    }
                    curTurns++;
                    turnsSinceNC++;
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (20 * (1 + itemDrop))) numWrits++;
                }                     
                
                // COMBAT: JANITOR
                if (curEnc == "janitor") {     
                    int dropRoll = rng.nextInt(100) + 1;
                    if (dropRoll <= (20 * (1 + itemDrop))) hasMatches = true;

                    curTurns++;
                    turnsSinceNC++;
                }          
                
                // NONCOMBAT
                if (curEnc == "noncombat") {     
                    if (curseLevel >= 3 || hasMatches) {
                        curTurns++;
                        totalTurns = totalTurns + curTurns;
                        turnsSinceNC = 0;
                        break;                          
                    }
                    else {
                        turnsSinceNC = 0;
                    }
                }      
            }      
            
            // The Hidden Office Building
            
            curTurns = 0;
            
            combatArr.clear();
            combatArr.add("headhunter");
            combatArr.add("accountant");
            combatArr.add("lawyer");
            if (!janitorsMigrated) {
                combatArr.add("janitor");
            }

            ts.clear();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());         
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                if (turnsSinceNC >= 5) {
                    turnsSinceNC = 0;
                    curType = "noncombat";
                    curEnc = "noncombat";
                }
                else {
                    curType = "combat";
                    listVar = "combatAdvs";
                    queueVar = "combatQueue";          
                }

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                if (curType == "combat") {
                    // Add encounter to queue and chop off end of queue
                    ((List)ts.get(queueVar)).add(0, curEnc);
                    if (((List)ts.get(queueVar)).size() > 5) {
                        List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                        ((List)ts.get(queueVar)).retainAll(toKeep);
                    }
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: HEADHUNTER
                if (curEnc == "headhunter") {      
                    if (numWrits > 0) {
                        numWrits--;
                    }
                    else {
                        curTurns++;      
                    }
                    turnsSinceNC++;
                }                      
                
                // COMBAT: ACCOUNTANT
                if (curEnc == "accountant") {  
                    if (reportPages < 5 && whichSniffed != "accountant") {
                        whichSniffed = "accountant";                        
                    }
                    if (reportPages >= 5 && numWrits > 0) {
                        numWrits--;
                    }
                    else {
                        reportPages++;
                        curTurns++;
                    }
                    turnsSinceNC++;
                }       

                // COMBAT: LAWYER
                if (curEnc == "lawyer") {    
                    if (reportPages >= 5 && whichSniffed != "lawyer") {
                        whichSniffed = "lawyer";                          
                    }
                    if (reportPages >= 5 && hasClip && turnsSinceNC >= 2 && numWrits > 0) {
                        numWrits--;
                    }
                    else {
                        curTurns++;
                        int dropRoll = rng.nextInt(100) + 1;
                        if (dropRoll <= (20 * (1 + itemDrop))) numWrits++;  
                    }
                    turnsSinceNC++;
                }                     
                
                // COMBAT: JANITOR
                if (curEnc == "janitor") {     
                    if (numWrits > 0) {
                        numWrits--;
                    }
                    else {
                        curTurns++;      
                    }
                    turnsSinceNC++;
                }          
                
                // NONCOMBAT
                if (curEnc == "noncombat") {     
                    if (!hasClip) {
                        hasClip = true;
                        curTurns++;
                        turnsSinceNC = 1;
                    }
                    else if (hasClip && reportPages >= 5) {
                        curTurns++;
                        totalTurns = totalTurns + curTurns;
                        allData.add(totalTurns);
                        break;
                    }
                }      
            }            
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }      
    
    public static Statistics runOldKnoll(int numTimes, int combatRate, boolean shouldSniff) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false,
                    hasTank = false,
                    hasSpring = false,
                    hasCog = false,
                    hasSprocket = false,
                    hasTires = false;
            double curTurns = 0;
            String whichSniffed = "";

            List combatArr = new ArrayList();
            combatArr.add("crossdresser");
            combatArr.add("flyslayer");
            combatArr.add("gearhead");
            combatArr.add("gearhead");
            combatArr.add("piebaker");
            combatArr.add("plungermaster");
            combatArr.add("tirejuggler");
            combatArr.add("warchef");
            combatArr.add("bugbear");
            combatArr.add("oneeyed");
            
            List NCAdvs = new ArrayList();
            NCAdvs.add(0, "toga");
            NCAdvs.add(1, "workshop");             

            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());
            ts.put("NCAdvs", NCAdvs);
            ts.put("NCQueue", new ArrayList());              
            ts.put("done", 0);             
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                // Combat/NC
                while (curType == "none") {
                    // Combat or noncombat?
                    int rngNC = rng.nextInt(100) + 1;

                    // Noncombats
                    if (rngNC > combatRate) {
                        curType = "noncombat";
                        listVar = "NCAdvs";
                        queueVar = "NCQueue";                         
                    }
                    else {
                        curType = "combat";
                        listVar = "combatAdvs";
                        queueVar = "combatQueue";                    
                    }    
                }

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: USELESS
                if (curEnc == "crossdresser" || curEnc == "flyslayer" || curEnc == "piebaker" || 
                    curEnc == "plungermaster" || curEnc == "warchef" || curEnc == "bugbear" || 
                    curEnc == "oneeyed" ) {      
                    curTurns++;
                } 

                // COMBAT: TIRES
                if (curEnc == "tirejuggler") {
                    hasTires = true;
                    curTurns++;
                }       

                // COMBAT: GEARHEAD
                if (curEnc == "gearhead") {     
                    if (shouldSniff && hasTires && whichSniffed != "gearhead") {
                        whichSniffed = "gearhead";
                    }
                    curTurns++;
                    int howMany = rng.nextInt(2) + 2;
                    // Toolbox drops
                    for (int x = 0; x < howMany; x++) {
                        int whichItem = rng.nextInt(4) + 1;
                        switch (whichItem) {
                            case 1:
                                hasCog = true;
                                break;
                            case 2:
                                hasTank = true;
                                break;
                            case 3:
                                hasSpring = true;
                                break;
                            case 4:
                                hasSprocket = true;
                                break;
                            default:
                                break;
                        }
                    }
                }        
                
                // NONCOMBAT: TOGA PARTY
                if (curEnc == "toga") {
                    curTurns++;
                }
                
                // NONCOMBAT: WORKSHOP
                if (curEnc == "workshop") {
                    hasCog = true;
                    hasSpring = true;
                    hasSprocket = true;
                    curTurns++;
                }

                // Are we done?
                if (hasSpring && hasCog && hasSprocket && hasTank && hasTires) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }  
    
    public static Statistics runNewKnoll(int numTimes, boolean shouldSniff) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false,
                    hasTank = false,
                    hasSpring = false,
                    hasCog = false,
                    hasSprocket = false,
                    hasTires = false;
            double curTurns = 0;
            String whichSniffed = "";

            List combatArr = new ArrayList();
            combatArr.add("gearhead");
            combatArr.add("tirejuggler");
            combatArr.add("bugbear");           

            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());                    
            
            while (!isDone) {
            
                String listVar = "";
                String queueVar = "";      
                String curType = "none";
                String curEnc = "none";                

                curType = "combat";
                listVar = "combatAdvs";
                queueVar = "combatQueue";                    

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: USELESS
                if (curEnc == "bugbear") {      
                    curTurns++;
                } 

                // COMBAT: TIRES
                if (curEnc == "tirejuggler") {
                    hasTires = true;
                    curTurns++;
                }       

                // COMBAT: GEARHEAD
                if (curEnc == "gearhead") {     
                    if (shouldSniff && hasTires && whichSniffed != "gearhead") {
                        whichSniffed = "gearhead";
                    }
                    curTurns++;
                    int howMany = rng.nextInt(2) + 2;
                    // Toolbox drops
                    for (int x = 0; x < howMany; x++) {
                        int whichItem = rng.nextInt(4) + 1;
                        switch (whichItem) {
                            case 1:
                                hasCog = true;
                                break;
                            case 2:
                                hasTank = true;
                                break;
                            case 3:
                                hasSpring = true;
                                break;
                            case 4:
                                hasSprocket = true;
                                break;
                            default:
                                break;
                        }
                    }
                }        

                // Are we done?
                if (hasSpring && hasCog && hasSprocket && hasTank && hasTires) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }      
    
    public static Statistics runNiche(int numTimes, int remainingEvil) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            String whichSniffed = "";
            double curTurns = 0;

            List combatArr = new ArrayList();
            combatArr.add("slick");
            combatArr.add("senile");
            combatArr.add("dirty");        
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curType = "combat";
                String curEnc = "none";                

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: DIRTY OLD LIHC
                if ("dirty".equals(curEnc)) {      

                    if (whichSniffed == "") {
                        // sniff it
                        whichSniffed = "dirty";
                    }
                    
                    remainingEvil = remainingEvil - 3;                  
                    curTurns++;
                } 

                // COMBAT: OTHER LIHCS
                if (curEnc == "slick" || curEnc == "senile") {      
                    remainingEvil--;
                    curTurns++;
                }                

                // Are we done?
                if (remainingEvil <= 25) {
                    allData.add(curTurns);
                    isDone = true;
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;         
    }
    
    public static Statistics runCyrpt(int numTimes, int numSculptures) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
        
            double curTurns = 0;
            
            int nookEvil = 50,
                nicheEvil = 50,
                crannyEvil = 50,
                alcoveEvil = 50;

            for (int x = 0; x < numSculptures; x++) {
                int rngEvil = rng.nextInt(2);
                nookEvil = nookEvil - 4 - rngEvil;
                rngEvil = rng.nextInt(2);
                nicheEvil = nicheEvil - 4 - rngEvil;
                rngEvil = rng.nextInt(2);
                crannyEvil = crannyEvil - 4 - rngEvil;
                rngEvil = rng.nextInt(2);
                alcoveEvil = alcoveEvil - 4 - rngEvil;
            }

            if (nookEvil > 25) {
                Statistics defiledNook = runNook(1, 2.5, nookEvil);
                curTurns = curTurns + defiledNook.getMean();
            }

            if (nicheEvil > 25) {
                Statistics defiledNiche = runNiche(1, nicheEvil);
                curTurns = curTurns + defiledNiche.getMean();
            }

            if (crannyEvil > 25) {
                Statistics defiledCranny = runCranny(1, 65, 64, crannyEvil);
                curTurns = curTurns + defiledCranny.getMean();
            }

            if (alcoveEvil > 25) {
                Statistics defiledAlcove = runAlcove(1, 65, 200, alcoveEvil);
                curTurns = curTurns + defiledAlcove.getMean();
            }        

            allData.add(curTurns);
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;         
    }
    
    public static Statistics runHitS(int numTimes, double itemDrop, boolean needsKey) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        int neededCharts = (needsKey) ? 3 : 2;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            double curTurns = 0;
            
            int numStars = 0,
                numLines = 0,
                numCharts = 0;

            List combatArr = new ArrayList();
            combatArr.add("astronomer");
            combatArr.add("astronomer");
            combatArr.add("bishop");
            combatArr.add("jewels");
            combatArr.add("warrior");
            combatArr.add("junk");
            combatArr.add("willie");
            combatArr.add("sword");
            combatArr.add("snake");
            combatArr.add("twig");
            combatArr.add("skinflute");
            
            String whichSniffed = "";

            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curEnc = "none";   
                String curType = "combat";

                boolean noAstronomer = false;
                
                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        if (item == "astronomer" && noAstronomer) {
                            // do not add
                        }
                        else {
                            tempList.add(item);
                        }
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        if (whichSniffed == "astronomer") {
                            tempList.add(whichSniffed);
                            tempList.add(whichSniffed);
                            tempList.add(whichSniffed);                            
                        }
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (whichEnc == "astronomer") {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            noAstronomer = true;
                            continue;
                        }
                        else {
                            curEnc = whichEnc;
                        }                        
                    }
                    else if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: ASTRONOMER
                if (curEnc == "astronomer") {   
                    if (numCharts < neededCharts && whichSniffed != curEnc) {
                        whichSniffed = curEnc;
                    }
                    numCharts++;
                    curTurns++;
                }      
                
                // COMBAT: SKINFLUTE
                if (curEnc == "skinflute") {   
                    if (numCharts >= neededCharts && whichSniffed != curEnc) {
                        whichSniffed = curEnc;
                    }
                    numLines++;
                    numLines++;
                    numStars++;
                    numStars++;
                    curTurns++;
                }          
                
                if (curEnc == "bishop" || curEnc == "junk" || curEnc == "willie") {   
                    if (numCharts >= neededCharts && numLines < (numStars - 4)) {
                        whichSniffed = curEnc;
                    }                    
                    numLines++;
                    numLines++;
                    numStars++;
                    curTurns++;
                }                     

                if (curEnc == "warrior" || curEnc == "sword" || curEnc == "twig") {   
                    if (numCharts >= neededCharts && numStars < (numLines - 2)) {
                        whichSniffed = curEnc;
                    }                          
                    numLines++;
                    numStars++;
                    numStars++;
                    curTurns++;
                }                     
                
                if (curEnc == "jewels") {   
                    if (numCharts >= neededCharts && numStars < (numLines - 2)) {
                        whichSniffed = curEnc;
                    }                      
                    numStars++;
                    numStars++;
                    numStars++;
                    curTurns++;
                }       
                            
                if (curEnc == "snake") {   
                    if (numCharts >= neededCharts && numLines < (numStars - 4)) {
                        whichSniffed = curEnc;
                    }                          
                    numLines++;
                    numLines++;
                    numLines++;
                    curTurns++;
                }                     
                
                if (numCharts >= neededCharts && whichSniffed == "astronomer") {
                    whichSniffed = "";
                }
                
                if (neededCharts == 2 && numCharts >= 2 && 
                   ((numStars >= 10 && numLines >= 9) || (numStars >= 11 && numLines >= 8) || (numStars >= 12 && numLines >= 7))) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }
                if (neededCharts == 3 && numCharts >= 3 && 
                   ((numStars >= 18 && numLines >= 16) || (numStars >= 19 && numLines >= 15) || (numStars >= 20 && numLines >= 14))) {
                    isDone = true;
                    allData.add(curTurns);
                    break;
                }                
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;       
    }  
    
    public static Statistics runFearMan(int numTimes) {
        
        Random rng = new Random();
        
        List<Double> allData = new ArrayList<Double>();
        int i = 0;
        
        for (i = 0; i < numTimes; i++) {
            
            boolean isDone = false;
            String whichSniffed = "";
            double curTurns = 0;
            int numWhite = 0;

            List combatArr = new ArrayList();
            combatArr.add("possessions");
            combatArr.add("skull");
            combatArr.add("spider");        
            
            HashMap ts = new HashMap();
            ts.put("combatAdvs", combatArr);
            ts.put("combatQueue", new ArrayList());            
            
            while (!isDone) {
            
                String listVar = "combatAdvs";
                String queueVar = "combatQueue";      
                String curType = "combat";
                String curEnc = "none";                

                // Pick encounter
                while (curEnc == "none") {
                    List tempList = new ArrayList();
                    for (Object item : (List)ts.get(listVar)) {
                        tempList.add(item);
                    }
                    if (curType == "combat" && whichSniffed != "") {
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                        tempList.add(whichSniffed);
                    }
                    
                    int listSize = tempList.size();
                    int whichNum = rng.nextInt(listSize);
                    String whichEnc = tempList.get(whichNum).toString();

                    // Queue rejection
                    if (((List)ts.get(queueVar)).contains(whichEnc) && whichEnc != whichSniffed) {
                        int rngReject = rng.nextInt(100) + 1;
                        if (rngReject > 75) {
                            curEnc = whichEnc;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        curEnc = whichEnc;
                    } 
                }

                // Add encounter to queue and chop off end of queue
                ((List)ts.get(queueVar)).add(0, curEnc);
                if (((List)ts.get(queueVar)).size() > 5) {
                    List toKeep = ((List)ts.get(queueVar)).subList(0, 5);
                    ((List)ts.get(queueVar)).retainAll(toKeep);
                }

                // Now we have the encounter. Let's do this.

                // COMBAT: SKULL
                if ("skull".equals(curEnc)) {
                    if (whichSniffed == "") {
                        whichSniffed = "skull";
                    }
                    numWhite = numWhite + 5;               
                    curTurns++;
                } 

                // COMBAT: OTHER
                if (curEnc == "possessions" || curEnc == "spider") {      
                    numWhite++;
                    curTurns++;
                }                

                // Are we done?
                if (numWhite >= 30) {
                    allData.add(curTurns);
                    isDone = true;
                    break;
                }
            }
        }
        
        Statistics newStat = new Statistics(allData.toArray(new Double[allData.size()]));
        
        return newStat;         
    }    
}